﻿/**
 * Created in 2012-2-14.
 */
package kit4j.tests.jdk.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 
 * @author MiniKnife
 * 
 */
public class TestClass {
	
	static interface SuperInterface {
		;
	}
	
	static interface SubInterface extends SuperInterface {
		;
	}
	
	static class SuperClass implements SubInterface {
		
	}
	
	static class SubClass extends SuperClass {
		
	}

	/**
	 * @param args
	 * @throws NoSuchFieldException 
	 * @throws SecurityException 
	 */
	public static void main(String[] args) throws SecurityException, NoSuchFieldException {
		// testGetDeclardProperty(String.class);

		// testShowObject(new Integer(2));

//		System.out.println(classToString(String.class));
//		
//		System.out.println(String.class.getDeclaredField("value"));
//		testGetInterfaces(SubClass.class);
		testIsInstance();
	}
	
	static void testGetInterfaces(Class<?> clazz) {
		if(clazz == null) {
			return;
		}
		
		for(Class<?> c : clazz.getInterfaces()) {
			System.out.println(classToString(c));
			testGetInterfaces(c);
		}
		
		testGetInterfaces(clazz.getSuperclass());
	}

	static void testGetDeclardProperty(Class<?> clazz) {
		StringBuilder declardSb = new StringBuilder();

		for (Method m : clazz.getDeclaredMethods()) {
			declardSb.append(methodToString(m));
			declardSb.append("\n");
		}

		System.out.println(declardSb.toString());

		System.out.println("-----------------------");

		StringBuilder noDeclardSb = new StringBuilder();

		for (Method m : clazz.getMethods()) {
			noDeclardSb.append(methodToString(m));
			noDeclardSb.append("\n");
		}

		System.out.println(noDeclardSb.toString());
	}

	static void testShowObject(Object obj) {
		Class<?> clazz = obj.getClass();
		StringBuilder sb = new StringBuilder();

		for (Field f : clazz.getDeclaredFields()) {
			sb.append(fieldToString(obj, f));
			sb.append(";\n");
		}

		sb.append("\n");

		for (Method m : clazz.getDeclaredMethods()) {
			sb.append(methodToString(m));
			sb.append("\n");
		}

		System.out.println(sb.toString());
	}

	static String classToString(Class<?> clazz) {
		StringBuilder sb = new StringBuilder();

		sb.append(Modifier.toString(clazz.getModifiers()));
		sb.append(" ");
		sb.append(clazz.getCanonicalName());
		sb.append(" ");
		sb.append(extendsClassToString(clazz.getSuperclass()));
		sb.append(" ");
		sb.append(implementsToString(clazz.getInterfaces()));
		sb.append("{\n");
		
		for(Field f : clazz.getDeclaredFields()) {
			sb.append("\t");
			sb.append(fieldToString(f));
			sb.append(";\n");
		}
		
		sb.append("\n");
		
		for (Method m : clazz.getDeclaredMethods()) {
			sb.append("\t");
			sb.append(methodToString(m));
			sb.append("\n");
		}
		
		sb.append("}");

		return sb.toString();
	}

	static String constructorToString(Constructor<?> con) {
		StringBuilder sb = new StringBuilder();

		return sb.toString();
	}

	static String methodToString(Method method) {
		StringBuilder sb = new StringBuilder();

		sb.append(Modifier.toString((method.getModifiers())));
		sb.append(" ");
		sb.append(method.getReturnType().getCanonicalName());
		sb.append(" ");
		sb.append(method.getName());
		sb.append("(");
		sb.append(parametersToString(method.getParameterTypes()));
		sb.append(") ");
		sb.append(throwsToString(method.getExceptionTypes()));
		sb.append(" {}");

		return sb.toString();
	}

	static String fieldToString(Field field) {
		StringBuilder sb = new StringBuilder();

		sb.append(Modifier.toString(field.getModifiers()));
		sb.append(" ");
		sb.append(field.getType().getCanonicalName());
		sb.append(" ");
		sb.append(field.getName());

		return sb.toString();
	}

	static String fieldToString(Object obj, Field field) {
		StringBuilder sb = new StringBuilder();

		sb.append(Modifier.toString(field.getModifiers()));
		sb.append(" ");
		sb.append(field.getType().getCanonicalName());
		sb.append(" ");
		sb.append(field.getName());

		try {
			Object value = field.get(obj);

			sb.append(" = ");
			sb.append(value.toString());
		} catch (Exception e) {
		}

		return sb.toString();
	}

	static String extendsClassToString(Class<?> superClass) {
		if (superClass != null) {
			return "extends " + superClass.getCanonicalName();
		} else {
			return "";
		}
	}

	static String implementsToString(Class<?>[] interfaces) {
		if (interfaces.length != 0) {
			StringBuilder sb = new StringBuilder();
			
			sb.append("implements ");
			
			for(Class<?> i : interfaces) {
				sb.append(i.getCanonicalName());
				sb.append(", ");
			}
			
			sb.delete(sb.length() - 2, sb.length());

			return sb.toString();
		} else {
			return "";
		}
	}

	static String parametersToString(Class<?>[] parameters) {
		if (parameters.length > 0) {
			StringBuilder sb = new StringBuilder();

			for (Class<?> e : parameters) {
				sb.append(e.getCanonicalName());
				sb.append(", ");
			}

			sb.delete(sb.length() - 2, sb.length());

			return sb.toString();
		} else {
			return "";
		}
	}

	static String throwsToString(Class<?>[] exceptions) {
		if (exceptions.length > 0) {
			StringBuilder sb = new StringBuilder();

			sb.append("throws ");

			for (Class<?> e : exceptions) {
				sb.append(e.getCanonicalName());
				sb.append(", ");
			}

			sb.delete(sb.length() - 2, sb.length());

			return sb.toString();
		} else {
			return "";
		}
	}
	
	static void testIsInstance() {
		Class<?> clazz = String.class;
		
		String str = null;
		System.out.println(clazz.isInstance(str));
		
		str = "";
		System.out.println(clazz.isInstance(str));
		
		str = null;
		System.out.println(clazz.isInstance(str));
	}

}
